package com.smallkingson.ylib.net.download;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.smallkingson.ylib.core.Yr;

import org.apache.http.HttpStatus;

public class YDownloadTask {

	private DownloadFile mDownloadFile = null;
	private ThreadDAO mDao = null;
	private long mFinised = 0;
	public boolean isPause = false;
	private int mThreadCount = 1;
	private List<DownloadThread> mDownloadThreadList = null;
	private YDownloads.DownloadListener downloadListener;
	private Handler handler;

	public YDownloadTask(Context context, Handler handler,
			DownloadFile downloadFile, int count) {
		this.setHandler(handler);
		this.mDownloadFile = downloadFile;
		this.mThreadCount = count;
		mDao = new ThreadDAO(context);
	}

	public void downLoad() {
		YDownloads.sendMessage(handler, YDownloads.WHAT_DOWNLOAD_BEFORE,
				mDownloadFile);
		List<ThreadInfo> threadInfos = mDao.getThreads(mDownloadFile.getUrl());
		ThreadInfo threadInfo = null;
		if (threadInfos == null || 0 == threadInfos.size()
				|| threadInfos.size() != mThreadCount) {
			if (threadInfos.size() != mThreadCount) {
				Yr.i("线程数更新");
				mDao.deleteThread(mDownloadFile.getUrl());
			}
			threadInfos = new ArrayList<ThreadInfo>();
			long len = mDownloadFile.getFileLength() / mThreadCount;
			for (int i = 0; i < mThreadCount; i++) {
				threadInfo = new ThreadInfo(i, mDownloadFile.getUrl(), len * i,
						(i + 1) * len - 1, 0);
				if (mThreadCount - 1 == i) {
					threadInfo.setEnd(mDownloadFile.getFileLength());
				}
				threadInfos.add(threadInfo);
				mDao.insertThread(threadInfo);
			}
		}
		for (ThreadInfo info : threadInfos) {
			Yr.i("分配线程完毕", "id: " + info.getId() + ",start: " + info.getStart()
					+ ",end: " + info.getEnd());
		}
		mDownloadThreadList = new ArrayList<DownloadThread>();
		for (ThreadInfo info : threadInfos) {
			DownloadThread thread = new DownloadThread(info);
			YDownloads.downloadExecutorService.execute(thread);
			mDownloadThreadList.add(thread);
		}
	}

	private class DownloadThread implements Runnable {
		private ThreadInfo mThreadInfo = null;
		public boolean isFinished = false;

		public DownloadThread(ThreadInfo mInfo) {
			this.mThreadInfo = mInfo;
		}

		@Override
		public void run() {
			HttpURLConnection connection = null;
			RandomAccessFile raf = null;
			InputStream inputStream = null;

			try {
				URL url = new URL(mThreadInfo.getUrl());
				connection = (HttpURLConnection) url.openConnection();
				connection.setConnectTimeout(5000);
				connection.setRequestMethod("GET");
				long start = mThreadInfo.getStart() + mThreadInfo.getFinished();
				connection.setRequestProperty("Range", "bytes=" + start + "-"
						+ mThreadInfo.getEnd());
				Yr.i("start downLoad", start, mThreadInfo.getEnd(),
						mThreadInfo.getEnd() - start + 1,
						connection.getContentLength());
				File file = new File(mDownloadFile.getLocalPath(),
						mDownloadFile.getFileName());
				raf = new RandomAccessFile(file, "rwd");
				raf.seek(start);
				mFinised += mThreadInfo.getFinished();
				Yr.i("connection.getResponseCode()",connection.getResponseCode());
				if (connection.getResponseCode() == HttpStatus.SC_PARTIAL_CONTENT) {
					inputStream = connection.getInputStream();
					byte buf[] = new byte[1024];
					int len = 0;
					long time = System.currentTimeMillis();
					Yr.i();
					while ((len = inputStream.read(buf)) > 0) {
						raf.write(buf, 0, len);
						mFinised += len;
						mThreadInfo
								.setFinished(mThreadInfo.getFinished() + len);
						mDownloadFile.setFinished(mFinised);
						if (System.currentTimeMillis() - time > 1000) {
							time = System.currentTimeMillis();
							long f = mFinised * 100
									/ mDownloadFile.getFileLength();
							Yr.i(f, mFinised, mDownloadFile.getFileLength());
							mDao.updateThread(mThreadInfo);
							YDownloads.sendMessage(handler,
									YDownloads.WHAT_DOWNLOAD_UPDATE,
									mDownloadFile);
						}
						if (isPause) {
							Log.i("mThreadInfo", mThreadInfo.getId()
									+ "finished = " + mThreadInfo.getFinished());
							return;
						}
					}
					long f = mFinised * 100 / mDownloadFile.getFileLength();
					Yr.i(f, mFinised, mDownloadFile.getFileLength());
					Yr.i("线程: " + mThreadInfo.getId() + "下载完成",
							mThreadInfo.getFinished());
					isFinished = true;
					checkAllThreadFinished();
				}
			} catch (Exception e) {
				Message message = Message.obtain();

				Object[] objects = new Object[2];
				objects[0] = mDownloadFile;
				objects[1] = e;
				message.what = YDownloads.WHAT_DOWNLOAD_ERROR;
				message.obj = objects;
				getHandler().sendMessage(message);
				Yr.logError(e);
			} finally {
				try {
					if (connection != null) {
						connection.disconnect();
					}
					if (raf != null) {
						raf.close();
					}
					if (inputStream != null) {
						inputStream.close();
					}
				} catch (Exception e2) {
					Yr.logError(e2);
				}
			}
		}
	}

	private synchronized void checkAllThreadFinished() {
		boolean allFinished = true;

		for (DownloadThread thread : mDownloadThreadList) {
			if (!thread.isFinished) {
				allFinished = false;
				break;
			}
		}

		if (allFinished) {
			mDao.deleteThread(mDownloadFile.getUrl());
			YDownloads.sendMessage(handler, YDownloads.WHAT_DOWNLOAD_UPDATE,
					mDownloadFile);
			mDownloadFile.from = YDownloads.From.URL;
			YDownloads.sendMessage(handler, YDownloads.WHAT_DOWNLOAD_SUCCESS,
					mDownloadFile);
		}
	}

	public YDownloads.DownloadListener getDownloadListener() {
		return downloadListener;
	}

	public void setDownloadListener(YDownloads.DownloadListener downloadListener) {
		this.downloadListener = downloadListener;
	}

	public Handler getHandler() {
		return handler;
	}

	public void setHandler(Handler handler) {
		this.handler = handler;
	}
}
